/*
 * Copyright (c) 2023 Beijing HuaQing YuanJian Education Technology Co., Ltd
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "hal_bsp_wifi.h"
#include "hal_bsp_mqtt.h"
#include "hal_bsp_pcf8574.h"
#include "hal_bsp_structAll.h"
#include "cJSON.h"
#include "string.h"
#include "hi_io.h"
#include "hi_gpio.h"

#define DEVICE_ID "001" //本设备ID
osMutexId_t Mutex_ID_SW1;
osMutexId_t Mutex_ID_SW2;
#define SW1 HI_IO_NAME_GPIO_1
#define SW2 HI_IO_NAME_GPIO_2
#define KEY HI_IO_NAME_GPIO_5 
#define SERVER_IP_ADDR "110.41.63.154"
#define SERVER_IP_PORT 1883
#define MQTT_TOPIC_SUB "QTClient"
#define MQTT_TOPIC_PUB "hi3861Client"
#define TASK_STACK_SIZE (1024 * 5)
#define TASK_INIT_TIME 2 // s
#define MQTT_RECV_TASK_TIME (200 * 1000) // us

//智能开关信息结构体
typedef struct 
{
    /* data */
    char* hi_device_id;  //设备ID
    // uint16_t hi_switch_id;  //开关ID
    // uint16_t hi_sw_value;   //开关值
}device_data_t;

//初始化本设备的信息
device_data_t this_device = {
    .hi_device_id = DEVICE_ID,  
    // .hi_switch_id = 0,
    // .hi_sw_value = 0
};

tn_pcf8574_io_t pcf8574_io = {0}; // IO扩展芯片的引脚
osThreadId_t mqtt_send_task_id;   // mqtt订阅数据任务
osThreadId_t mqtt_recv_task_id;   // mqtt发布数据任务

cJSON *device_id = NULL;
cJSON *sw_id = NULL;
cJSON *sw_value = NULL;
uint16_t sw1_state = 0;
uint16_t sw2_state = 0;


hi_void gpio_callback(void)
{
    printf("key down...\r\n");
    hi_gpio_set_ouput_val(HI_GPIO_IDX_2,0);

    osMutexAcquire(Mutex_ID_SW1, osWaitForever);    // 请求互斥锁
    if(sw1_state ==0)sw1_state=1;
    else if(sw1_state==1)sw1_state=0;
    hi_gpio_set_ouput_val(HI_GPIO_IDX_1,sw1_state);
    osMutexRelease(Mutex_ID_SW1);   // 释放互斥锁
    osMutexAcquire(Mutex_ID_SW2, osWaitForever);    // 请求互斥锁
    if(sw2_state ==0)sw2_state=1;
    else if(sw2_state==1)sw2_state=0;
    hi_gpio_set_ouput_val(HI_GPIO_IDX_2,sw2_state);
    osMutexRelease(Mutex_ID_SW2);   // 释放互斥锁
    printf("sw1 and sw2 is close!\r\n");
}

int8_t mqtt_sub_payload_callback(unsigned char *topic, unsigned char *payload)
{
    printf("[info] topic:[%s]    recv<== %s\r\n", topic, payload);
    
    cJSON *my_mqtt_recv = cJSON_Parse((const char *)payload); 
    device_id = cJSON_GetObjectItem(my_mqtt_recv, "device_id");
    sw_id     = cJSON_GetObjectItem(my_mqtt_recv, "sw_id"); 
    sw_value  = cJSON_GetObjectItem(my_mqtt_recv, "sw_value"); 
    if(strcmp(device_id->valuestring , this_device.hi_device_id) == 0)
    {
        printf("id is real\r\n");
        if(sw_id->valueint == 1){
            if(sw_value->valueint == 1){
                osMutexAcquire(Mutex_ID_SW1, osWaitForever);    // 请求互斥锁
                sw1_state = 1;
                osMutexRelease(Mutex_ID_SW1);   // 释放互斥锁
                hi_gpio_set_ouput_val(HI_GPIO_IDX_1,1);
                printf("sw1 is open!\r\n");
            }
            else{
                osMutexAcquire(Mutex_ID_SW1, osWaitForever);    // 请求互斥锁
                sw1_state = 0;
                osMutexRelease(Mutex_ID_SW1);   // 释放互斥锁
                hi_gpio_set_ouput_val(HI_GPIO_IDX_1,0);
                printf("sw1 is close!\r\n");
            }
        }
        else if(sw_id->valueint == 2){
            if(sw_value->valueint == 1){
                osMutexAcquire(Mutex_ID_SW2, osWaitForever);    // 请求互斥锁
                sw2_state = 1;
                osMutexRelease(Mutex_ID_SW2);   // 释放互斥锁
                hi_gpio_set_ouput_val(HI_GPIO_IDX_2,1);
                printf("sw2 is open!\r\n");
            }
            else{
                osMutexAcquire(Mutex_ID_SW2, osWaitForever);    // 请求互斥锁
                sw2_state = 0;
                osMutexRelease(Mutex_ID_SW2);   // 释放互斥锁
                hi_gpio_set_ouput_val(HI_GPIO_IDX_2,0);
                printf("sw2 is close!\r\n");
            }
        } 
    }
    else{
        printf("%s\r\n",device_id->valuestring);
        printf("id is error\r\n");
    }
    cJSON_Delete(my_mqtt_recv);
}
void mqtt_recv_task(void)
{
    while (1) {
        MQTTClient_sub();
        usleep(MQTT_RECV_TASK_TIME);
    }
}
void mqtt_send_task(void)
{
    // 连接Wifi
    if (WiFi_connectHotspots("wifi-zzl", "82868753") != WIFI_SUCCESS) {
        printf("[error] WiFi_connectHotspots\r\n");
    }

    // 连接MQTT服务器
    if (MQTTClient_connectServer(SERVER_IP_ADDR, SERVER_IP_PORT) != 0) {
        printf("[error] MQTTClient_connectServer\r\n");
    } else {
        printf("[success] MQTTClient_connectServer\r\n");
    }
    sleep(TASK_INIT_TIME);

    // 初始化MQTT客户端
    if (MQTTClient_init("hi3861", "hi3861", "82868753") != 0) {
        printf("[error] MQTTClient_init\r\n");
    } else {
        printf("[success] MQTTClient_init\r\n");
    }
    sleep(TASK_INIT_TIME);

    // 订阅Topic
    if (MQTTClient_subscribe(MQTT_TOPIC_SUB) != 0) {
        printf("[error] MQTTClient_subscribe\r\n");
    } else {
        printf("[success] MQTTClient_subscribe\r\n");
    }
    sleep(TASK_INIT_TIME);

    osThreadAttr_t options;
    options.name = "mqtt_recv_task";
    options.attr_bits = 0;
    options.cb_mem = NULL;
    options.cb_size = 0;
    options.stack_mem = NULL;
    options.stack_size = TASK_STACK_SIZE;
    options.priority = 12;

    mqtt_recv_task_id = osThreadNew((osThreadFunc_t)mqtt_recv_task, NULL, &options);
    if (mqtt_recv_task_id != NULL) {
        printf("ID = %d, Create mqtt_recv_task_id is OK!\r\n", mqtt_recv_task_id);
    }

    char* pub_str = NULL;
    while (1) {
        //开关1的状态消息
        cJSON* cjson_SW1_state = cJSON_CreateObject();
        cJSON_AddStringToObject(cjson_SW1_state, "device_id", this_device.hi_device_id);
        cJSON_AddNumberToObject(cjson_SW1_state, "sw_id", 1);
        // cJSON_AddNumberToObject(cjson_SW1_state, "online", 1);
        cJSON_AddNumberToObject(cjson_SW1_state, "sw_value", sw1_state);
        pub_str = cJSON_Print(cjson_SW1_state);
        MQTTClient_pub(MQTT_TOPIC_PUB, pub_str, strlen(pub_str));
        cJSON_Delete(cjson_SW1_state);
        free(pub_str);
        sleep(1);
        //开关1的状态消息
        cJSON* cjson_SW2_state = cJSON_CreateObject();
        cJSON_AddStringToObject(cjson_SW2_state, "device_id", this_device.hi_device_id);
        cJSON_AddNumberToObject(cjson_SW2_state, "sw_id", 2);
        // cJSON_AddNumberToObject(cjson_SW1_state, "online", 1);
        cJSON_AddNumberToObject(cjson_SW2_state, "sw_value", sw2_state);
        pub_str = cJSON_Print(cjson_SW2_state);
        MQTTClient_pub(MQTT_TOPIC_PUB, pub_str, strlen(pub_str));
        cJSON_Delete(cjson_SW2_state);
        free(pub_str);
        pub_str = NULL;
        sleep(1);
    }
}

static void network_wifi_mqtt_example(void)
{
    printf("Enter network_wifi_mqtt_example()!\r\n");

    PCF8574_Init();

    //创建互斥锁
    Mutex_ID_SW1 = osMutexNew(NULL);
    if (Mutex_ID_SW1 != NULL) {
        printf("ID = %d, Create Mutex_ID is OK!\n", Mutex_ID_SW1);
    }
    Mutex_ID_SW2 = osMutexNew(NULL);
    if (Mutex_ID_SW2 != NULL) {
        printf("ID = %d, Create Mutex_ID is OK!\n", Mutex_ID_SW2);
    }

    hi_gpio_init();                                            // GPIO初始化
    hi_io_set_pull(SW1, HI_IO_PULL_NONE);                        // 设置GPIO上拉
    hi_io_set_func(SW1, HI_IO_FUNC_GPIO_1_GPIO);              // 设置IO1为GPIO功能
    hi_gpio_set_dir(SW1, HI_GPIO_DIR_OUT);                      // 设置GPIO为输入模式
    hi_gpio_init();                                            // GPIO初始化
    hi_io_set_pull(SW2, HI_IO_PULL_NONE);                        // 设置GPIO上拉
    hi_io_set_func(SW2, HI_IO_FUNC_GPIO_2_GPIO);              // 设置IO2为GPIO功能
    hi_gpio_set_dir(SW2, HI_GPIO_DIR_OUT);                      // 设置GPIO为输入模式

    hi_gpio_init();                                            // GPIO初始化
    hi_io_set_pull(KEY, HI_IO_PULL_UP);                        // 设置GPIO上拉
    hi_io_set_func(KEY, HI_IO_FUNC_GPIO_5_GPIO);              // 设置IO5为GPIO功能
    hi_gpio_set_dir(KEY, HI_GPIO_DIR_IN);                      // 设置GPIO为输入模式
    hi_gpio_register_isr_function(KEY,                         // KEY按键引脚
                                  HI_INT_TYPE_EDGE,            // 下降沿检测
                                  HI_GPIO_EDGE_FALL_LEVEL_LOW, // 低电平时触发
                                  &gpio_callback,              // 触发后调用的回调函数
                                  NULL);                       // 回调函数的传参值

    p_MQTTClient_sub_callback = &mqtt_sub_payload_callback;

    osThreadAttr_t options;
    options.name = "mqtt_send_task";
    options.attr_bits = 0;
    options.cb_mem = NULL;
    options.cb_size = 0;
    options.stack_mem = NULL;
    options.stack_size = TASK_STACK_SIZE;
    options.priority = 12;

    mqtt_send_task_id = osThreadNew((osThreadFunc_t)mqtt_send_task, NULL, &options);
    if (mqtt_send_task_id != NULL) {
        printf("ID = %d, Create mqtt_send_task_id is OK!\r\n", mqtt_send_task_id);
    }
}
SYS_RUN(network_wifi_mqtt_example);